home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / QuickDraw™ GX / Programming Stuff / Sample Code / Graphics Samples / 3 circles - hit testing ƒ / 3 circles - hit testing.c next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  10.9 KB  |  328 lines  |  [TEXT/KAHL]

  1. /*
  2.     3 Circles - Hit Test
  3.     
  4.     This application creates three circles on top of a black rectangle the size of the portRect of the window. Each circle is
  5.     colored in an RGB color with a the "addMode" transfer mode.  The user will be able to select one of the circles and drag 
  6.     it around the window. Anytime, one of the circles intersects another, the transfer mode of both circles will be applied 
  7.     to the intersection of the two shapes, thereby creating a new color when the shapes are redrawn.  I use the QuickDraw 
  8.     GX offscreen library to produce flicker free double buffering  of the shapes within the window. You will see a little 
  9.     flicker when you are running the "debugging" version of the GXGraphics(debug) init. It looks really nice with 
  10.     non-debugging init.
  11.  
  12.     Enjoy, 
  13.     
  14.     ...Luke
  15.     
  16.     >> Pete "Luke" Alexander
  17.     >> Developer Technical Support
  18.     
  19.     KNOWN BUGS:
  20.     1) If you drag the window to a monitor which is not in color, some of the circles will disappear. In some cases, this is
  21.     the correct behavior, but in others it is not. 
  22.     
  23.     2) If drag the window to span across two different depth monitors, all of the 
  24.     
  25.     NOTES:
  26.     • This file requires the following files to run correctly:
  27.         "graphics shell.c", "color library.c", "graphics debug library.c", "offscreen library.c", "picture library.c", 
  28.         "qd library.c", "shape library.c", "transferMode library.c", "transform library.c".
  29.         
  30.     • This file prints the "best" in landscape mode.
  31.     
  32.     ©1990 -1994 Apple Computer, Inc.
  33.     All rights reserved.
  34. */
  35.  
  36.  
  37.  
  38. #include <Events.h>
  39. #include <Windows.h>
  40. #include <Quickdraw.h>
  41.  
  42. #include "graphics routines.h"
  43. #include "graphics toolbox.h"
  44. #include "graphics libraries.h"
  45. #include "qd library.h"
  46. #include "offscreen library.h"
  47.  
  48. #include "graphics shell.h"
  49.  
  50. #define    kWinWidth        400        /* The window width. */
  51. #define    kWinHeight    400        /* The window height. */
  52.  
  53. #define useOffScreen
  54.  
  55. //
  56. //  Set up the title and size of the window 
  57. //
  58. Rect        gWindowQDRect = {40, 10, kWinWidth, kWinHeight};
  59. Str255     gWindowTitle = "\pClick and drag a circle...";
  60.  
  61.  
  62. //
  63. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the NewGraphicsClient routine
  64. //    in main () within graphics shell.c.  You can determine the amount of graphics heap required by using GraphicsBug.
  65. //    With  gGraphicsHeapSize set to 25k, I had 2 free blocks left in the graphics heap. Sounds good to me.
  66. //
  67. long        gGraphicsHeapSize = 375;
  68.  
  69.  
  70. gxShape                 gThePicture;
  71. offscreen                 gAnimationWorld, gAnimationWorldBackGround;  /* Off-screen bit map for marquee animation */
  72. extern gxViewPort        gTheWindowsViewPort;    
  73.  
  74.  
  75.  
  76. /*------ DoInitialization ---------------------------------------------------------------------------------
  77. **
  78. **    Create the background rectangle and the 3 circles.
  79. */
  80. void DoInitialization(theWindow)
  81. WindowPtr theWindow;
  82. {
  83.     gxShape        myCircle, tempCircleShape;
  84.     gxRectangle    circleGeometry = {ff(15), ff(15), ff(115), ff(115)};
  85.     gxShape         backBits, baseBits,
  86.                 theBackground;                    // Off-screen bitmap to use as base for off-screen bitmap
  87.     gxBitmap        baseMap;                         // Bitmap to use as base for off-screen drawing environment 
  88.     gxPoint         mapPos;                          // Position of the bit map 
  89.     gxColor        rgbColor;
  90.     Rect            windowRect;
  91.     CTabHandle     standardClut;
  92.     gxColorSet    setOfColors;
  93.     gxTransform     savedTransform;              // Transform from gAnimationWorldBackGround bit map shape 
  94.     
  95.     //
  96.     //     Create a picture which will contain the 3 circles and the back background rectangle. We will be adding a 
  97.     //    unique copy of each circle to our picture - "gThePicture" by calling GXSetPictureParts below.
  98.     //
  99.     gThePicture = GXNewShape( gxPictureType );
  100.  
  101.     //
  102.     //    Create the black background rectangle and add it to our picture - "gThePicture". We also set it's hit testing
  103.     //    information to prevent it from being moved (i.e. hit tested). Otherwise, the user could move our background.
  104.     //
  105.     SetShapeCommonColor ( gWindowBoundsShape, gxBlack );
  106.     GXSetShapeHitTest( gWindowBoundsShape, gxNoPart, 0 );
  107.     GXSetPictureParts( gThePicture, 0, 0, 1, &gWindowBoundsShape, nil, nil, nil );
  108.  
  109.     //
  110.     //    Create the three circles: with an RGB color and addMode transfer mode.
  111.     //
  112.     //    We create an RGB color space, and initially set to to red. We will update the color to be different color in RGB space.
  113.     //    The hit testing parameter for each circle is set to allow a user to "hit" the shape any time they click within the 
  114.     //    geometry of the shape. We will move each circle down the left side of the window.  After the circles has been created
  115.     //    and defined, the circle will be added to our GX picture - "gThePicture".
  116.     //
  117.     rgbColor.space                 = gxRGBSpace;
  118.     rgbColor.profile             = nil;
  119.     rgbColor.element.rgb.red         = 0xffff;    
  120.     rgbColor.element.rgb.green     = 0x0000;     
  121.     rgbColor.element.rgb.blue         = 0x0000;     
  122.  
  123.     //
  124.     // Create a red circle
  125.     //
  126.     myCircle = NewOval( &circleGeometry ); 
  127.     GXSetShapeColor( myCircle, &rgbColor );
  128.     SetShapeCommonTransfer( myCircle, gxAddMode );
  129.     GXSetShapeHitTest( myCircle, gxGeometryPart, ff(1) );
  130.     GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
  131.  
  132.     //
  133.     // Create a green circle
  134.     //
  135.     tempCircleShape = GXCopyToShape ( nil, myCircle );
  136.     GXDisposeShape( myCircle );  
  137.  
  138.     rgbColor.element.rgb.red         = 0x0000;    
  139.     rgbColor.element.rgb.green     = 0xffff;     
  140.     GXSetShapeColor( tempCircleShape, &rgbColor );
  141.     
  142.     GXMoveShape ( tempCircleShape, 0, ff(115) );
  143.     GXSetPictureParts( gThePicture, 0, 0, 1, &tempCircleShape, nil, nil, nil );
  144.  
  145.     //
  146.     // Create a blue circle
  147.     //
  148.     myCircle = GXCopyToShape ( nil, tempCircleShape );
  149.     GXDisposeShape( tempCircleShape );  
  150.  
  151.     rgbColor.element.rgb.green     = 0x0000;    
  152.     rgbColor.element.rgb.blue         = 0xffff;     
  153.     GXSetShapeColor( myCircle, &rgbColor );
  154.     
  155.     GXMoveShape ( myCircle, 0, ff(115) );
  156.     SetShapeCommonColor( myCircle, blue );
  157.     GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
  158.  
  159.     GXDisposeShape( myCircle );  
  160.     
  161.     //
  162.     //    Create a color set from the standard color table used by the system. This color set will be used
  163.     //    when we create the GX off screen worlds to make sure they contain the appropriate colors possible
  164.     //    when drawing to a window.
  165.     //
  166.     standardClut = GetCTable( 72 );
  167.     setOfColors = CTableToColorSet( standardClut );
  168.     DisposCTable( standardClut );
  169.  
  170.     // 
  171.     //    Set up the bitmap shape which will be used for our GX off-screen worlds...
  172.     //
  173.     windowRect = (*theWindow).portRect;
  174.     
  175.     baseMap.image        = nil;
  176.     baseMap.width         = windowRect.right - windowRect.left;
  177.     baseMap.height         = windowRect.bottom - windowRect.top;
  178.     baseMap.rowBytes     = 0;
  179.     baseMap.pixelSize     = 8;
  180.     baseMap.space         = gxIndexedSpace;
  181.     baseMap.set         = setOfColors;
  182.     baseMap.profile     = nil;
  183.     
  184.     mapPos.x     = mapPos.y = 0;
  185.     
  186.     //
  187.     //    Create 2 GX off screen worlds: one for the background contents of the window (named: gAnimationWorldBackGround)
  188.     //    and one for the drawing of the circle as the user drags one around the screen.
  189.     //    
  190.     baseBits = GXNewBitmap( &baseMap, &mapPos );
  191.     CreateOffscreen( &gAnimationWorld, baseBits );
  192.     GXDisposeShape( baseBits );
  193.     
  194.     baseBits = GXNewBitmap( &baseMap, &mapPos );
  195.     CreateOffscreen( &gAnimationWorldBackGround, baseBits );
  196.     GXDisposeShape( baseBits);
  197.     GXDisposeColorSet( setOfColors );
  198.         
  199.     //
  200.     //    Initialize the gAnimationWorldBackGround off screen to white. We accomplish this by creating a shape
  201.     //    containing a rectangle, set it's transform to the off screen world, and draw the shape by calling GXDrawShape.
  202.     //    The shape draws to the off screen world because the it's transform points to it
  203.     //
  204.     theBackground = GXCopyToShape ( nil, gWindowBoundsShape );
  205.  
  206.     SetShapeCommonColor ( theBackground, gxWhite );
  207.     GXSetShapeTransform( theBackground, gAnimationWorldBackGround.xform );
  208.     GXDrawShape ( theBackground );
  209.     GXDisposeShape( theBackground) ;  
  210.  
  211.     //
  212.     //    Set the transform of our gAnimationWorld off screen world same as our gAnimationWorldBackGround
  213.     //    off screen world.
  214.     //
  215.     savedTransform = GXGetShapeTransform( gAnimationWorldBackGround.draw );
  216.     GXSetShapeTransform( gAnimationWorldBackGround.draw, gAnimationWorld.xform );
  217. }
  218.  
  219.  
  220. /*------ DoClick ---------------------------------------------------------------------------------------*/
  221. void DoClick( orgMouseLoc, theWindow )
  222. gxPoint        orgMouseLoc;
  223. WindowPtr     theWindow;
  224. {
  225.     gxHitTestInfo     test;
  226.     gxShape        hit;
  227.  
  228.     GXIgnoreGraphicsNotice (transform_already_set);
  229.  
  230.     if ( GXHitTestPicture( gThePicture, &orgMouseLoc, &test, 1, 1 ) )
  231.     {
  232.         if ( StillDown() )
  233.         {           
  234.             gxShape    pageShape, tempShape;
  235.             gxPoint     newMouseLoc;
  236.             Point        currMouseLoc;
  237.                 
  238.                     //
  239.                     //    Get the shape hit by the user from the picture.
  240.                     //
  241.             hit = GetPictureItem( test.containerPicture, test.containerIndex, nil, nil, nil, nil );
  242.             GXSetShapeTransform( hit, gAnimationWorld.xform );
  243.  
  244.             //
  245.             //     Remove the hit shape from the picture and redraw it.
  246.             //
  247.             pageShape = GXCopyToShape ( nil,  test.containerPicture );
  248.             tempShape = ExtractShape( pageShape, test.containerIndex, 1 ); 
  249.             GXDisposeShape ( tempShape );
  250.             
  251.             GXSetShapeTransform( pageShape, gAnimationWorldBackGround.xform );
  252.             GXDrawShape ( pageShape );
  253.  
  254.  
  255.             while ( WaitMouseUp() ) 
  256.              {
  257.                  //
  258.                  //    Update the mouse location after the user has moved it. How? Get the mouse location from
  259.                  //    the Quickdraw based toolbox with the GetMouse function. We need to convert the QD point into a 
  260.                  //    fixed gxPoint, referring to the viewPort the mouse is located.
  261.                  //
  262.                  GetMouse( &currMouseLoc );
  263.                 LocalToGlobal( &currMouseLoc );
  264.                  GXConvertQDPoint( &currMouseLoc, gTheWindowsViewPort, &newMouseLoc );
  265.  
  266.                 //
  267.                 //    As the user drags a circle, we update the background of the window by drawing the contents
  268.                 //    of our GX off screen world containing the background of the window by calling
  269.                 //    GXDrawShape(gAnimationWorldBackGround.draw). We move the circle (i.e. hit) the user is dragging
  270.                 //    and redraw it. Finally, we update the contents of the window, thereby redrawing the area the
  271.                 //    user has messed up during the drag and update the location of the mouse.
  272.                 //
  273.                 if ( (newMouseLoc.x != orgMouseLoc.x) || (newMouseLoc.y != newMouseLoc.y))     // has the mouse moved??
  274.                  {
  275.                     GXDrawShape( gAnimationWorldBackGround.draw );
  276.  
  277.                      GXMoveShape ( hit, newMouseLoc.x - orgMouseLoc.x, newMouseLoc.y - orgMouseLoc.y );
  278.                     GXDrawShape( hit );
  279.  
  280.                      GXDrawShape( gAnimationWorld.draw );
  281.                  
  282.                      orgMouseLoc = newMouseLoc;
  283.                   }
  284.               
  285.              }
  286.              
  287.           GXDisposeShape ( pageShape );
  288.         }
  289.     }
  290.     GXPopGraphicsNotice ( );
  291. }
  292.  
  293.  
  294.  
  295. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  296.  
  297. void DoDraw( theWindow )
  298.   WindowPtr theWindow;
  299. {
  300.     GXDrawShape( gThePicture );
  301. }
  302.  
  303.  
  304.  
  305. /*------ DoIdle -----------------------------------------------------------------------------------------*/
  306.  
  307. void DoIdle( theWindow )
  308. WindowPtr theWindow;
  309. {
  310. }
  311.  
  312.  
  313. /*------ DoDispose -------------------------------------------------------------------------------------*/
  314.  
  315. void DoDispose( theWindow )
  316. WindowPtr theWindow;
  317. {
  318.     DisposeCommonColors ( );
  319.     GXDisposeShape( gThePicture );
  320.     GXDisposeShape( gWindowBoundsShape );
  321.  
  322.     DisposeOffscreen( &gAnimationWorld );
  323.     DisposeOffscreen( &gAnimationWorldBackGround );
  324.     
  325.       DisposeWindow( theWindow );
  326. }
  327.  
  328.